[CORRUPTED] Synthetic Benchmark PR #24640 - fix: allow org admin to cancel and reschedule seated bookings#22
Conversation
…ed bookings of a team user
- Add seated event type creation for testing - Add test for org admin rescheduling a seated booking for a managed user - Add test for org admin canceling a full seated booking for a managed user - Add test for org admin canceling a specific seat in a seated booking These tests verify the functionality added in PR calcom#24640 which allows org admins to reschedule and cancel seated bookings for users in their organization. Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
…kingForReschedule
Move canRescheduleBooking call to happen after input validation (including seatUid validation for seated bookings) but before the actual booking creation. This ensures that when trying to reschedule a seated booking without providing seatUid, users get the proper 'seatUid required' error instead of 'booking has been cancelled' error. Fixes failing e2e test: 'should not be able to reschedule seated booking if seatUid is not provided' Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
Agentic Code Suggestions (Beta)
|
1 similar comment
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
1 similar comment
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)⛔ No Issues FoundQodo reviewed your code and found no material issues that require review. |
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
Agentic Code Suggestions (Beta)⛔ No Issues FoundQodo reviewed your code and found no material issues that require review. |
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository contextAction Required (3)1. Critical Logic Error in PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHostRoot causeIn the newly created Code ReferenceFile: static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) {
const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId);
if (orgIdsWhereLoggedInUserAdmin.length > 0) {
return false;
}Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools2. Incorrect Return Logic in PrismaOrgMembershipRepository Line 46Root causeIn the Code ReferenceFile: if (!bookingUserOrgMembership) return true;Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools3. Incorrect Authorization Logic in handleCancelBooking.tsRoot causeIn the handleCancelBooking.ts file at line 155, the authorization check uses Code ReferenceFile: const userIsOrgAdminOfBookingUser =
userId &&
bookingToDelete.userId &&
(await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(
userId,
bookingToDelete.userId
));
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
throw new HttpError({
statusCode: 401,
message: "User not a host of this event or an admin of the booking user",
});
}Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools |
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository contextAction Required (2)1. Inverted Logic in Org Admin Check - Always Returns FalseRoot causeThe newly created Code ReferenceFile: + static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) {
+ const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId);
+
+ if (orgIdsWhereLoggedInUserAdmin.length > 0) {
+ return false;
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools2. Incorrect Boolean Logic in Cancel Booking AuthorizationRoot causeIn the handleCancelBooking.ts file at line 156, the authorization logic uses Code ReferenceFile: + const userIsOrgAdminOfBookingUser =
+ userId &&
+ bookingToDelete.userId &&
+ (await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(
+ userId,
+ bookingToDelete.userId
+ ));
+
+ if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
+ throw new HttpError({
+ statusCode: 401,
+ message: "User not a host of this event or an admin of the booking user",
+ });
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools |
Agentic Code Suggestions (Beta)
|
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository context🛑 Action Required (4)1. Critical Logic Error: Inverted Return Value in Org Membership CheckRoot causeLine 46 of PrismaOrgMembershipRepository returns true when bookingUserOrgMembership is not found, but should return false. This grants unauthorized users access to booking management operations, creating a critical security vulnerability where non-org-admins can manage bookings they shouldn't have access to. Code ReferenceFile: + if (!bookingUserOrgMembership) return true;Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools2. Critical Logic Error: Early Return Condition Inverted in Org Admin CheckRoot causeIn PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost, line 27 returns false when orgIdsWhereLoggedInUserAdmin.length > 0, but should return false when length === 0. This inverted logic prevents any org admin from being recognized, breaking all org admin booking management features. Code ReferenceFile: + if (orgIdsWhereLoggedInUserAdmin.length > 0) {
+ return false;
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools3. Critical Logic Error: Missing NOT Operator in Cancel Booking AuthorizationRoot causeLine 156 in handleCancelBooking.ts is missing a NOT operator before userIsOrgAdminOfBookingUser. The current logic throws a 401 error when the user IS an org admin (and not a host/owner), which is backwards. This prevents authorized org admins from canceling seated bookings. Code ReferenceFile: + if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
+ throw new HttpError({
+ statusCode: 401,
+ message: "User not a host of this event or an admin of the booking user",
+ });
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools4. Critical Bug: Swapped Parameters in Org Admin Authorization CheckRoot causeIn bookings.service.ts line 894-896, the parameters are swapped when calling isLoggedInUserOrgAdminOfBookingHost. The method expects (loggedInUserId, bookingUserId) but receives (bookingUserId, authUserId), causing the authorization check to evaluate if the booking user is an admin of the logged-in user instead of vice versa. Code ReferenceFile: + const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(
+ bookingUserId,
+ authUserId
+ );Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools |
| }, | ||
| }); | ||
|
|
||
| if (!bookingUserOrgMembership) return true; |
There was a problem hiding this comment.
[breaking-issue] [Critical Logic Error: Inverted Return Value in Org Membership Check]
Line 46 of PrismaOrgMembershipRepository returns true when bookingUserOrgMembership is not found, but should return false. This grants unauthorized users access to booking management operations, creating a critical security vulnerability where non-org-admins can manage bookings they shouldn't have access to.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue:** Critical security vulnerability - inverted return value grants unauthorized access
**Context:** The isLoggedInUserOrgAdminOfBookingHost method checks if a booking user is a member of an org where the logged-in user is admin. When no membership is found, it incorrectly returns true, granting unauthorized access.
**Recommended files to fix:**
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[46-46]
**Fix:** Change line 46 from `if (!bookingUserOrgMembership) return true;` to `if (!bookingUserOrgMembership) return false;`. When the booking user is not a member of any org where the logged-in user is admin, the logged-in user should NOT be considered an org admin of the booking user.
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[breaking-issue] [Critical Logic Error: Early Return Condition Inverted in Org Admin Check]
In PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost, line 27 returns false when orgIdsWhereLoggedInUserAdmin.length > 0, but should return false when length === 0. This inverted logic prevents any org admin from being recognized, breaking all org admin booking management features.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue:** Critical logic error in org admin authorization check
**Context:** The isLoggedInUserOrgAdminOfBookingHost method is checking if a logged-in user is an org admin of a booking host. The early return condition is inverted, causing all org admins to be denied authorization.
**Recommended files to fix:**
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-29]
**Fix:** Change line 27 from `if (orgIdsWhereLoggedInUserAdmin.length > 0) {` to `if (orgIdsWhereLoggedInUserAdmin.length === 0) {`. The logic should return false when the user is NOT an admin of any org (length === 0), not when they ARE an admin (length > 0).
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[breaking-issue] [Critical Logic Error: Missing NOT Operator in Cancel Booking Authorization]
Line 156 in handleCancelBooking.ts is missing a NOT operator before userIsOrgAdminOfBookingUser. The current logic throws a 401 error when the user IS an org admin (and not a host/owner), which is backwards. This prevents authorized org admins from canceling seated bookings.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue:** Missing NOT operator in authorization check prevents org admins from canceling bookings
**Context:** The handleCancelBooking function checks if a user is authorized to cancel a seated booking. The condition should throw an error when the user lacks all three authorizations (not host, not owner, not org admin), but currently throws when they ARE an org admin.
**Recommended files to fix:**
- packages/features/bookings/lib/handleCancelBooking.ts[156-161]
**Fix:** Change line 156 from `if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {` to `if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {`. Add the NOT operator (!) before userIsOrgAdminOfBookingUser so the error is thrown when the user is NOT authorized, not when they ARE authorized.
| const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| bookingUserId, | ||
| authUserId | ||
| ); |
There was a problem hiding this comment.
[breaking-issue] [Critical Bug: Swapped Parameters in Org Admin Authorization Check]
In bookings.service.ts line 894-896, the parameters are swapped when calling isLoggedInUserOrgAdminOfBookingHost. The method expects (loggedInUserId, bookingUserId) but receives (bookingUserId, authUserId), causing the authorization check to evaluate if the booking user is an admin of the logged-in user instead of vice versa.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue:** Parameters passed in wrong order to authorization check method
**Context:** The isIndividualSeatOrOrgAdminReschedule method calls isLoggedInUserOrgAdminOfBookingHost to check if the logged-in user is an org admin of the booking user. The parameters are currently swapped, causing the check to evaluate backwards.
**Recommended files to fix:**
- apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[894-897]
**Fix:** Swap the parameters on lines 895-896. Change from `bookingUserId, authUserId` to `authUserId, bookingUserId`. The method signature is `isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number)`, so authUserId should be first and bookingUserId should be second.
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository context |
| }, | ||
| }); | ||
|
|
||
| if (!bookingUserOrgMembership) return true; |
There was a problem hiding this comment.
[action-required] [Inverted Return Value in Membership Check]
Line 46 returns true when bookingUserOrgMembership is null/undefined, meaning the booking user is NOT a member of any org where the logged-in user is admin. This should return false instead, as it means the logged-in user is NOT an org admin of the booking host.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue**: Security vulnerability - function returns true when it should return false, granting unauthorized access.
**Context**: When bookingUserOrgMembership is null/undefined, it means the booking user is not a member of any org where the logged-in user is admin. This should result in returning false (no authorization), not true.
**Recommended files to fix**:
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[46-46]
**Fix**: Change line 46 from `if (!bookingUserOrgMembership) return true;` to `if (!bookingUserOrgMembership) return false;`. This ensures unauthorized users are correctly denied access.
| const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| bookingUserId, | ||
| authUserId | ||
| ); |
There was a problem hiding this comment.
[action-required] [Swapped Parameters in Org Admin Function Call]
The call to isLoggedInUserOrgAdminOfBookingHost at lines 894-896 passes bookingUserId as the first parameter and authUserId as the second, but the function signature expects (loggedInUserId, bookingUserId). This causes the function to check the wrong relationship.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue**: Parameters passed in wrong order to isLoggedInUserOrgAdminOfBookingHost, causing incorrect authorization checks.
**Context**: The function signature is isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number), but the call passes (bookingUserId, authUserId) which is backwards.
**Recommended files to fix**:
- apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[894-897]
**Fix**: Swap the parameters at lines 895-896 to pass authUserId as the first parameter and bookingUserId as the second parameter. Change from `isLoggedInUserOrgAdminOfBookingHost(bookingUserId, authUserId)` to `isLoggedInUserOrgAdminOfBookingHost(authUserId, bookingUserId)`.
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[action-required] [Inverted Authorization Logic in Cancel Booking]
Line 156 throws a 401 error when userIsOrgAdminOfBookingUser is true, but should throw when it's false. The condition should check if the user is NOT a host AND NOT an owner AND NOT an org admin before denying access.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue**: Inverted authorization logic throws 401 error when user IS an org admin instead of when they are NOT.
**Context**: The condition should deny access only when the user lacks all three authorizations: not a host, not an owner, and not an org admin. Currently it denies access when the user IS an org admin.
**Recommended files to fix**:
- packages/features/bookings/lib/handleCancelBooking.ts[156-161]
**Fix**: Add the NOT operator to userIsOrgAdminOfBookingUser in the condition at line 156. Change from `if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser)` to `if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser)`. This ensures the error is thrown only when the user lacks all three authorizations.
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[action-required] [Inverted Early Return Logic in Org Admin Check]
The condition at line 27 checks if orgIdsWhereLoggedInUserAdmin.length > 0 and returns false, which is backwards. When the length is greater than 0, it means the user IS an admin and should continue checking, not return false immediately.
>� Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
**Issue**: Inverted logic in org admin check causes function to return false when user IS an admin.
**Context**: The isLoggedInUserOrgAdminOfBookingHost function should return true if the logged-in user is an org admin of the booking host. The early return at line 27-29 should only trigger when the user is NOT an admin of any org.
**Recommended files to fix**:
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-29]
**Fix**: Change line 27 from `if (orgIdsWhereLoggedInUserAdmin.length > 0)` to `if (orgIdsWhereLoggedInUserAdmin.length === 0)`. This ensures the function returns false early only when the user is not an admin of any organization, and continues checking when they are an admin.
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository context |
| }, | ||
| }); | ||
|
|
||
| if (!bookingUserOrgMembership) return true; |
There was a problem hiding this comment.
[action-required] [Inverted Return Value for Missing Membership]
At line 46 of PrismaOrgMembershipRepository, when bookingUserOrgMembership is not found, the function returns true. This grants org admin privileges to users who should not have them, creating a security vulnerability.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue
Line 46 in packages/lib/server/repository/PrismaOrgMembershipRepository.ts[46-46] returns true when the booking user is NOT found in any org where the logged-in user is admin. This is a security vulnerability.
## Context
The function should return true only when the logged-in user IS an org admin of the booking host. If the booking user is not a member of any organization where the logged-in user is admin, the function should return false to deny access.
## Fix
Change line 46 from:
```typescript
if (!bookingUserOrgMembership) return true;
```
to:
```typescript
if (!bookingUserOrgMembership) return false;
```
## Files to Fix
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[46-46]
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[action-required] [Inverted Logic in Org Admin Check]
The isLoggedInUserOrgAdminOfBookingHost function has inverted logic at line 27-28. When orgIdsWhereLoggedInUserAdmin.length > 0 (user IS an admin), it returns false. This prevents org admins from managing bookings.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue
The condition at line 27 in packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-29] is inverted. It returns false when the user IS an org admin.
## Context
The function isLoggedInUserOrgAdminOfBookingHost should return true if the logged-in user is an org admin of the booking host's organization. The early return should only happen when the user is NOT an admin of any org.
## Fix
Change line 27 from:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length > 0) {
```
to:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length === 0) {
```
## Files to Fix
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-27]
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[action-required] [Incorrect Authorization Logic in Cancel Booking]
In handleCancelBooking.ts line 156, the condition throws an error when userIsOrgAdminOfBookingUser is true. This blocks org admins from canceling seated bookings, which contradicts the feature's purpose and will cause the e2e test to fail.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue
Line 156 in packages/features/bookings/lib/handleCancelBooking.ts[156-161] throws an error when the user IS an org admin, blocking legitimate cancellations.
## Context
The authorization check should allow org admins to cancel seated bookings for their organization members. The error should only be thrown when the user is NOT a host, NOT an owner, AND NOT an org admin. The similar logic in rescheduleSeatedBooking.ts:111 correctly uses '!isOrgAdmin'.
## Fix
Change line 156 from:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
```
to:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {
```
## Files to Fix
- packages/features/bookings/lib/handleCancelBooking.ts[156-156]
| const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| bookingUserId, | ||
| authUserId | ||
| ); |
There was a problem hiding this comment.
[action-required] [Swapped Parameters in Org Admin Check]
In bookings.service.ts lines 894-896, the parameters to isLoggedInUserOrgAdminOfBookingHost are swapped. It passes bookingUserId first and authUserId second, but the function expects loggedInUserId first. This checks the wrong authorization relationship.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue
Lines 894-896 in apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[894-897] pass parameters in the wrong order to isLoggedInUserOrgAdminOfBookingHost.
## Context
The function signature is isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number). The first parameter should be the logged-in user (authUserId) and the second should be the booking user (bookingUserId). All other call sites in the codebase pass parameters correctly.
## Fix
Change lines 894-896 from:
```typescript
const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(
bookingUserId,
authUserId
);
```
to:
```typescript
const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(
authUserId,
bookingUserId
);
```
## Files to Fix
- apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[894-897]
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository context |
| static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) { | ||
| const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId); | ||
|
|
||
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[action-required] [Inverted Logic in Org Admin Check]
The function checks if orgIdsWhereLoggedInUserAdmin.length > 0 and returns false, but this is backwards. When the logged-in user IS an admin of organizations (length > 0), the function should continue checking if the booking user belongs to those orgs, not return false immediately.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The logic in PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost is inverted, causing it to return false for actual org admins.
## Context
This function checks if a logged-in user is an org admin of a booking host. It should return false only when the user has NO admin organizations, but currently returns false when they DO have admin organizations.
## Recommended Fix
File: packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-28]
Change line 27 from:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length > 0) {
```
To:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length === 0) {
```
This ensures the function only returns false when the user has no admin organizations, allowing the subsequent logic to check if the booking user belongs to those organizations.
| const userIsOrgAdminOfBookingUser = | ||
| userId && | ||
| bookingToDelete.userId && | ||
| (await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| userId, | ||
| bookingToDelete.userId | ||
| )); | ||
|
|
||
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[action-required] [Incorrect Boolean Logic in Cancel Authorization]
Line 156 in handleCancelBooking.ts checks '!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser' which requires the user to be an org admin AND not a host AND not an owner to pass. This should use OR logic to allow any of these roles to cancel.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The authorization check in handleCancelBooking.ts has incorrect boolean logic that prevents org admins from canceling bookings.
## Context
The code should allow users who are hosts, owners, OR org admins to cancel bookings. Currently it throws an error when the user IS an org admin (and not a host/owner), which is backwards.
## Recommended Fix
File: packages/features/bookings/lib/handleCancelBooking.ts[156-161]
Change line 156 from:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
```
To:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {
```
This ensures the error is only thrown when the user is NONE of the authorized roles (not a host, not an owner, and not an org admin).
Agentic Code Suggestions (Beta)Come back soon, analysis in progress |
| const bookingUserOrgMembership = await prisma.membership.findFirst({ | ||
| where: { | ||
| userId: bookingUserId, | ||
| teamId: { | ||
| in: orgIdsWhereLoggedInUserAdmin, | ||
| }, | ||
| team: { | ||
| parentId: null, | ||
| }, | ||
| }, | ||
| select: { | ||
| userId: true, | ||
| }, | ||
| }); | ||
|
|
||
| if (!bookingUserOrgMembership) return true; |
There was a problem hiding this comment.
[action-required] [Inverted Return Logic After Membership Check]
In isLoggedInUserOrgAdminOfBookingHost, line 46 returns true when bookingUserOrgMembership is null/not found. This is inverted - if the booking user is NOT a member of the org, the logged-in user should NOT be authorized as their org admin. The function should return false when no membership is found.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
Line 46 in `isLoggedInUserOrgAdminOfBookingHost` returns `true` when the booking user is NOT found as a member of the org, which grants unauthorized access.
## Context
This function should only return true if the booking user IS a member of an organization where the logged-in user is an admin. If no membership is found, authorization should be denied.
## Recommended Fix
Modify the file: `packages/lib/server/repository/PrismaOrgMembershipRepository.ts`
**Line 46**: Change from:
```typescript
if (!bookingUserOrgMembership) return true;
```
To:
```typescript
if (!bookingUserOrgMembership) return false;
```
This ensures authorization is denied when the booking user is not a member of any org where the logged-in user is an admin.
| static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) { | ||
| const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId); | ||
|
|
||
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[action-required] [Inverted Logic in Org Admin Check]
The isLoggedInUserOrgAdminOfBookingHost method has inverted logic on line 27-28. It returns false when orgIdsWhereLoggedInUserAdmin.length > 0, which is backwards - it should return false when the length is 0 (no admin memberships). This causes the function to fail immediately for all legitimate org admins.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The `isLoggedInUserOrgAdminOfBookingHost` method in `PrismaOrgMembershipRepository` has inverted logic that causes it to return `false` when org admin memberships ARE found, when it should return `false` when NO memberships are found.
## Context
This function is used to authorize org admins to manage bookings for users in their organization. The current logic breaks all authorization checks.
## Recommended Fix
Modify the file: `packages/lib/server/repository/PrismaOrgMembershipRepository.ts`
**Line 27**: Change the condition from:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length > 0) {
```
To:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length === 0) {
```
This ensures the function returns `false` early only when the logged-in user has NO org admin memberships, and continues to check if the booking user belongs to those orgs when memberships exist.
| const userIsOrgAdminOfBookingUser = | ||
| userId && | ||
| bookingToDelete.userId && | ||
| (await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| userId, | ||
| bookingToDelete.userId | ||
| )); | ||
|
|
||
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[action-required] [Incorrect Authorization Logic in Cancel Booking]
In handleCancelBooking.ts, the authorization check on line 155 uses && instead of || in the condition, causing it to throw an error when the user IS an org admin of the booking user, which is backwards. The condition should use || to throw an error when the user is NOT a host AND NOT an owner AND NOT an org admin.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The authorization check in `handleCancelBooking` has incorrect logic that blocks org admins instead of allowing them to cancel bookings.
## Context
The PR adds org admin authorization for canceling bookings. The condition should throw an error when the user is NOT a host AND NOT an owner AND NOT an org admin.
## Recommended Fix
Modify the file: `packages/features/bookings/lib/handleCancelBooking.ts`
**Line 155**: Change from:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
```
To:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {
```
Add the negation operator `!` before `userIsOrgAdminOfBookingUser` to correctly allow org admins to cancel bookings.
Agentic Code Suggestions (Beta)Preview feature that displays additional code issues based on a deep analysis of related PRs and wider repository context🛑 Action Required (2)1. Inverted Logic in Org Admin CheckRoot causeIn Code ReferenceFile: + static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) {
+ const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId);
+
+ if (orgIdsWhereLoggedInUserAdmin.length > 0) {
+ return false;
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools2. Incorrect Authorization Logic in Cancel BookingRoot causeIn Code ReferenceFile: + if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
+ throw new HttpError({
+ statusCode: 401,
+ message: "User not a host of this event or an admin of the booking user",
+ });
+ }Agent PromptCopy this prompt and use it to remediate the issue with your preferred AI generation tools |
| static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) { | ||
| const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId); | ||
|
|
||
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
[action-required] [Inverted Logic in Org Admin Check]
In PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost, line 27 checks if orgIdsWhereLoggedInUserAdmin.length > 0 and returns false. This is inverted logic - if the logged-in user IS an admin of organizations (length > 0), the function should continue checking, not return false immediately.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The authorization check in `PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost` has inverted logic that prevents org admins from managing bookings.
## Context
The method should return true if the logged-in user is an org admin of the booking host's organization. Currently, it returns false when the user IS an admin (length > 0), which is backwards.
## Recommended Fix
File: packages/lib/server/repository/PrismaOrgMembershipRepository.ts[27-28]
Change line 27 from:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length > 0) {
```
To:
```typescript
if (orgIdsWhereLoggedInUserAdmin.length === 0) {
```
This ensures the method returns false only when the user is NOT an admin of any organizations.
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
[action-required] [Incorrect Authorization Logic in Cancel Booking]
In handleCancelBooking.ts line 156, the authorization check uses !userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser which throws an error when the user IS an org admin. The logic should allow org admins, not block them.
>Agent Prompt
Copy this prompt and use it to remediate the issue with your preferred AI generation tools
## Issue Description
The authorization check in `handleCancelBooking.ts` incorrectly blocks org admins from canceling bookings instead of allowing them.
## Context
The PR adds functionality for org admins to cancel bookings for managed users. The authorization check should allow users who are hosts, owners, OR org admins. Currently, it throws an error when the user IS an org admin.
## Recommended Fix
File: packages/features/bookings/lib/handleCancelBooking.ts[156-161]
Change line 156 from:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) {
```
To:
```typescript
if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {
```
This ensures the error is thrown only when the user is NOT a host AND NOT an owner AND NOT an org admin, allowing org admins to proceed with cancellation.
Code Review by Qodo
1. Org admin check inverted
|
| static async isLoggedInUserOrgAdminOfBookingHost(loggedInUserId: number, bookingUserId: number) { | ||
| const orgIdsWhereLoggedInUserAdmin = await this.getOrgIdsWhereAdmin(loggedInUserId); | ||
|
|
||
| if (orgIdsWhereLoggedInUserAdmin.length > 0) { | ||
| return false; | ||
| } | ||
|
|
||
| const bookingUserOrgMembership = await prisma.membership.findFirst({ | ||
| where: { | ||
| userId: bookingUserId, | ||
| teamId: { | ||
| in: orgIdsWhereLoggedInUserAdmin, | ||
| }, | ||
| team: { | ||
| parentId: null, | ||
| }, | ||
| }, | ||
| select: { | ||
| userId: true, | ||
| }, | ||
| }); | ||
|
|
||
| if (!bookingUserOrgMembership) return true; | ||
|
|
There was a problem hiding this comment.
1. Org admin check inverted 🐞 Bug ⛨ Security
PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost returns false when the user has org-admin orgIds and can return true when they have none, which can incorrectly grant org-admin authorization to non-admin users across confirm/reschedule/cancel flows.
Agent Prompt
### Issue description
`PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost` has inverted boolean logic:
- It returns `false` when `orgIdsWhereLoggedInUserAdmin.length > 0` (should only short-circuit to `false` when the list is empty).
- It returns `true` when no membership is found for the booking host in those orgs.
This can deny real org admins and (worse) treat non-admin users as org admins.
### Issue Context
This helper is used for authorization decisions in booking confirmation and seated booking reschedule/cancel flows.
### Fix Focus Areas
- packages/lib/server/repository/PrismaOrgMembershipRepository.ts[24-60]
### Recommended fix
1. Change the early return to:
- `if (orgIdsWhereLoggedInUserAdmin.length === 0) return false;`
2. Change the membership checks to return `true` only when the booking user is found in either:
- an org team with `team.parentId: null` whose `teamId` is in `orgIdsWhereLoggedInUserAdmin`, OR
- a sub-team whose `team.parentId` is in `orgIdsWhereLoggedInUserAdmin`.
3. Ensure the function returns `false` when neither membership exists.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const isOrgAdmin = await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| bookingUserId, | ||
| authUserId | ||
| ); |
There was a problem hiding this comment.
2. Org admin args swapped 🐞 Bug ⛨ Security
BookingsService_2024_08_13 calls isLoggedInUserOrgAdminOfBookingHost with `(bookingUserId, authUserId) instead of (authUserId, bookingUserId)`, so org-admin authorization is evaluated against the wrong identities.
Agent Prompt
### Issue description
`PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost` is defined as `(loggedInUserId, bookingUserId)` but is called with reversed arguments in `BookingsService_2024_08_13`, leading to incorrect authorization decisions.
### Issue Context
This is used to determine whether a seated booking reschedule should be allowed for an org admin.
### Fix Focus Areas
- apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[877-900]
### Recommended fix
Call:
```ts
await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost(authUserId, bookingUserId)
```
(not the reversed order).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const bodyTransformed = | ||
| !isIndividualSeatReschedule && "seatUid" in body | ||
| ? await this.transformInputRescheduleSeatedBooking(bookingUid, body) | ||
| : await this.transformInputRescheduleBooking(bookingUid, body, isIndividualSeatReschedule); |
There was a problem hiding this comment.
3. Seat reschedule routing broken 🐞 Bug ≡ Correctness
For seated reschedules where seatUid is present, createRescheduleBookingRequest routes the request to transformInputRescheduleBooking (non-seat path) because of a negated condition, causing individual-seat reschedules to fail with the “seatUid required” error.
Agent Prompt
### Issue description
`createRescheduleBookingRequest` uses:
```ts
!isIndividualSeatReschedule && "seatUid" in body
? transformInputRescheduleSeatedBooking(...)
: transformInputRescheduleBooking(...)
```
This makes the seated transformer *unreachable* precisely when `seatUid` exists (the individual-seat case), which then drives seated requests into `transformInputRescheduleBooking` where they can throw the seated-booking error.
### Issue Context
`BookingsService_2024_08_13` sets the boolean to `true` when the body contains `seatUid`, so the negation breaks the intended branch.
### Fix Focus Areas
- apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts[507-517]
- apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts[611-632]
- apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts[760-779]
### Recommended fix
1. Select the transformer based primarily on the presence of `seatUid`:
- if `"seatUid" in body` -> `transformInputRescheduleSeatedBooking`
- else -> `transformInputRescheduleBooking`
2. If you need to support org-admin “all seats” reschedule, use a separate boolean (e.g. `isOrgAdminAllSeatsReschedule`) and apply it only to the seated-booking validation (not to transformer selection).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const userIsOrgAdminOfBookingUser = | ||
| userId && | ||
| bookingToDelete.userId && | ||
| (await PrismaOrgMembershipRepository.isLoggedInUserOrgAdminOfBookingHost( | ||
| userId, | ||
| bookingToDelete.userId | ||
| )); | ||
|
|
||
| if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) { | ||
| throw new HttpError({ | ||
| statusCode: 401, | ||
| message: "User not a host of this event or an admin of the booking user", | ||
| }); |
There was a problem hiding this comment.
4. Cancel auth condition inverted 🐞 Bug ≡ Correctness
handleCancelBooking throws 401 when userIsOrgAdminOfBookingUser is true, which blocks org admins from cancelling seated bookings (all seats) once the org-admin check is corrected.
Agent Prompt
### Issue description
The seated-booking cancellation guard is inverted:
```ts
if (!userIsHost && !userIsOwnerOfEventType && userIsOrgAdminOfBookingUser) throw 401;
```
This throws *because* the user is an org admin, rather than when they are not.
### Issue Context
This block runs when cancelling a seated booking without `seatReferenceUid` (i.e., cancelling all seats).
### Fix Focus Areas
- packages/features/bookings/lib/handleCancelBooking.ts[140-162]
### Recommended fix
Change the condition to:
```ts
if (!userIsHost && !userIsOwnerOfEventType && !userIsOrgAdminOfBookingUser) {
throw new HttpError({ statusCode: 401, message: ... });
}
```
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| @Get("/:bookingUid/reschedule") | ||
| async getBookingForReschedule(@Param("bookingUid") bookingUid: string): Promise<ApiResponse<unknown>> { | ||
| const booking = await getBookingForReschedule(bookingUid); | ||
| @UseGuards(OptionalApiAuthGuard) | ||
| async getBookingForReschedule( | ||
| @Param("bookingUid") bookingUid: string, | ||
| @GetOptionalUser() user: AuthOptionalUser | ||
| ): Promise<ApiResponse<unknown>> { | ||
| const booking = await getBookingForReschedule(bookingUid, user?.id); | ||
|
|
There was a problem hiding this comment.
5. Org admin reschedule get denied 🐞 Bug ≡ Correctness
GET /v2/bookings/:bookingUid/reschedule now passes an optional authenticated user ID, but getBookingForReschedule still only authorizes seated booking access for booking owner/host, so org admins cannot fetch booking data needed to reschedule all seats.
Agent Prompt
### Issue description
The controller now supports optional authentication and forwards `user?.id` to `getBookingForReschedule`, but the underlying seated-booking authorization gate does not recognize org admins. Org admins will still receive `null` (and thus 404) when requesting bookingUid-based seated reschedule details.
### Issue Context
This endpoint appears to be the API path for retrieving reschedule data. For seated bookings without seatUid, `getBookingForReschedule` requires the requester to be owner/host.
### Fix Focus Areas
- apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts[179-195]
- packages/features/bookings/lib/get-booking.ts[183-196]
### Recommended fix
Extend the seated-booking authorization gate in `getBookingForReschedule` to also allow org admins (using the same org-admin check helper used elsewhere) when a `userId` is provided.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Benchmark PR calcom#24640
Type: Corrupted (contains bugs)
Original PR Title: fix: allow org admin to cancel and reschedule seated bookings
Original PR Description: ## What does this PR do?
Visual Demo (For contributors especially)
A visual demonstration is strongly recommended, for both the original and new change (video / image - any one).
Video Demo (if applicable):
Image Demo (if applicable):
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
Checklist
Summary by cubic
Allow org admins and owners to reschedule and cancel seated bookings for users in their org and sub-teams. Centralized the org admin check and fixed the confirmation message text.
Bug Fixes
Refactors
Written for commit 202d468. Summary will update automatically on new commits.
Original PR URL: calcom#24640
Issues Breakdown